Kubernetes - Déploiement
Les machines
1 master et autant de worker que voulus seront utilisé.
Le tutoriel à été fait sur Ubuntu 20.04, avec la box vagrant bento/ubuntu20.04, version de box « 202112.19.0 » sur le provider Vmware Workstation.
2GB de Ram par machine suffisent..
Version de Vagrant (Windows) utilisée :
N :B : ovftools doit être installé sur votre machine pour le déploiement sur Workstation !
Le Vagrant file
IMAGE_NAME = "bento/ubuntu-20.04" # Image to use
MEM = 2048 # Amount of RAM
CPU = 2 # Number of processors (Minimum value of 2 otherwise it will not work)
MASTER_NAME="master" # Master node name
NODE_NETWORK_BASE = "192.168.45" # First three octets of the IP address that will be assign to all type of nodes
nodes = [
{ hostname: MASTER_NAME, box: IMAGE_NAME, mac:'00:50:56:25:03:95', numvcpus:'2', ip:"#{NODE_NETWORK_BASE}.30" },
{ hostname: 'worker-1', box:'bento/ubuntu-20.04', mac:'00:50:56:26:11:98', numvcpus:'2', ip:"#{NODE_NETWORK_BASE}.27" },
{ hostname: 'worker-2', box:'bento/ubuntu-20.04', mac:'00:50:56:27:11:98', numvcpus:'2', ip:"#{NODE_NETWORK_BASE}.28" }
]
Vagrant.configure("2") do |config|
nodes.each do |node|
config.vm.define node[:hostname] do |config|
config.vm.synced_folder('.', '/Vagrantfiles', type: 'rsync')
config.vm.box = node[:box]
config.vm.box_version = "202112.19.0"
config.vm.hostname= node[:hostname]
config.vm.disk :disk, size: "20GB", primary: true
config.vm.boot_timeout = 100
config.vm.graceful_halt_timeout = 100
config.ssh.insert_key = false
config.vm.provision "shell", path: "install.sh"
config.vm.provider "vmware_desktop" do |v|
v.gui = true
nat_device = "vmnet8"
v.linked_clone = false
v.vmx["ethernet0.connectionType"] = "nat"
v.vmx["memsize"] = "2048"
v.vmx["numvcpus"] = "2"
v.vmx["virtualHW.version"] = "11" #compatible Esxi 6.5
v.vmx["ethernet0.present"] = "true"
v.vmx["scsi0:0.size"] = "40000"
end
end
end
end
install.sh
#!/bin/bash
# Update the system
apt-get update -y
# Install the required packages
apt-get install -y vim net-tools sudo ssh curl htop open-vm-tools dnsutils gpg
# Usefull libs
sudo snap install yq
# Couples of prerequisites
sudo apt-get update
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo modprobe overlay
sudo modprobe br_netfilter
# NFS client
sudo apt-get install -y nfs-common
Puis rendez-vous dans le dossier en ligne de commande (ici Powershell en mode administrateur) ou se trouve votre Vagrantfile puis lancer la commande :
vagrant up
Installation de docker, kubeadm, kubelet et kubectl
Pré-requis
Sur la machine qui sera le master et sur toutes les autres machines, assurez-vous d'avoir installé les outils de base pour Kubernetes tels que Docker et kubeadm en suivant les instructions d'installation pour Ubuntu
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common gpg bash-completion
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubeadm kubelet kubectl
sudo usermod -aG docker $USER && newgrp docker #Uniquement si vous utilisez docker avec un utilisateur non root (ce sera normalement le cas)
Une fois ces prérequis installés, vous pouvez soit installer minikube, kind, ou un cluster k8s.
Minikube
Installer minikube.
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube
sudo mv minikube /usr/local/bin/
curl -sSL https://get.docker.com | sh
minikube start [options]
kubectl get node
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane,master 40m v1.20.0
Créer un cluster avec minikube :
$ minikube start --driver docker --nodes 3
😄 minikube v1.28.0 on Debian 11.5
✨ Using the docker driver based on user configuration
📌 Using Docker driver with root privileges
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
🔥 Creating docker container (CPUs=2, Memory=2200MB) ...
🐳 Preparing Kubernetes v1.25.3 on Docker 20.10.20 ...
[…]
🔗 Configuring CNI (Container Networking Interface) ...
[…]
👍 Starting worker node minikube-m02 in cluster minikube
[…]
🔎 Verifying Kubernetes components...
👍 Starting worker node minikube-m03 in cluster minikube
🚜 Pulling base image ...
🔥 Creating docker container (CPUs=2, Memory=2200MB) ...
[…]
🔎 Verifying Kubernetes components...
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
Puis essayer:
Cluster Kind
Kind (Kubernetes in Docker) permet de déployer un cluster Kubernetes de façon à ce que chacun des nodes du cluster tourne dans un container Docker.
Pour l'utiliser il suffit simplement d'installer Docker ainsi que la dernière release de Kind (https://github.com/kubernetes-sigs/kind/releases).
curl -Lo ./kind "https://kind.sigs.k8s.io/dl/v0.17.0/kind-$(uname)-amd64"
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
vagrant@worker-1:~$ kind
kind creates and manages local Kubernetes clusters using Docker container 'nodes'
Usage:
kind [command]
Available Commands:
build Build one of [node-image]
completion Output shell completion code for the specified shell (bash, zsh or fish)
create Creates one of [cluster]
delete Deletes one of [cluster]
export Exports one of [kubeconfig, logs]
get Gets one of [clusters, nodes, kubeconfig]
help Help about any command
load Loads images into nodes
version Prints the kind CLI version
Flags:
-h, --help help for kind
--loglevel string DEPRECATED: see -v instead
-q, --quiet silence all stderr output
-v, --verbosity int32 info log verbosity, higher value produces more output
--version version for kind
Use "kind [command] --help" for more information about a command.
Créer le cluster k8S.
kind create cluster --name k8s
HA Clusters
Kind permet également de mettre en place un cluster comportant plusieurs nodes, pour cela il faut utiliser un fichier de configuration. Par exemple, le fichier suivant (config.yaml) définit un cluster de 3 nodes: 1 master et 2 workers.
# config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
kind create cluster --name k8s-2 --config config.yaml
kind get clusters
Cluster K8S
Ne pas oublier d’installer DOCKER, KUBEADM, KUBELET ET KUBECTL, vu précédemment, sur chaque machine, master comme worker.
Pré-requis
Commun aux masters et workers
Installer d’abord les dépendances nécessaires (container runtime et quelques packages).
#curl -sSL https://luc.run/kubeadm/master.sh | bash
$ sudo swapoff -a #Désactiver le swap
L'installation avec le curl n'est pas forcément nécessaire, c'est un script préconçu de configuration initiale, qui peut différer suivant comment on décicde d'installer notre cluster. Si vous avez respectez les prérequis précédent, il ne sera normalement pas obligatoire.
Voici le contenu initial du script, cela peut aider :
# Set current version
VERSION=${VERSION:-"1.25.2"}
# Useful alias
echo 'alias k="kubectl"' >> $HOME/.bashrc
# Usefull libs
sudo snap install yq
# Cleanup first
rm -rf $HOME/.kube
sudo kubeadm reset -f || true
sudo apt-mark unhold kubelet kubeadm kubectl || true
sudo apt-get remove -y containerd kubelet kubeadm kubectl kubernetes-cni || true
sudo apt-get autoremove -y
sudo systemctl daemon-reload
# Couples of prerequisites
sudo apt-get update
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo modprobe overlay
sudo modprobe br_netfilter
# NFS client
sudo apt-get install -y nfs-common
# Installing packages
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt-get update
sudo apt-get install -y kubelet=${VERSION}-00 kubeadm=${VERSION}-00 kubectl=${VERSION}-00 kubernetes-cni
# Installing Containerd
sudo apt-get install containerd -y
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
sudo service containerd restart
sudo service kubelet restart
# Installing Helm client
sudo snap install helm --classic
# Configure crictl to use Containerd (it uses Docker by default)
cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
EOF
# Install etcdctl (linux amd64 or arm64)
ARCH=$(dpkg --print-architecture)
ETCDCTL_VERSION=v3.5.2
ETCDCTL_VERSION_FULL=etcd-${ETCDCTL_VERSION}-linux-$ARCH
wget https://github.com/etcd-io/etcd/releases/download/${ETCDCTL_VERSION}/${ETCDCTL_VERSION_FULL}.tar.gz
tar xzf ${ETCDCTL_VERSION_FULL}.tar.gz
sudo mv ${ETCDCTL_VERSION_FULL}/etcdctl /usr/bin/
rm -rf ${ETCDCTL_VERSION_FULL} ${ETCDCTL_VERSION_FULL}.tar.gz
# Install nerdctl
NERDCTL_VERSION=0.17.0
wget https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-${ARCH}.tar.gz
sudo tar Cxzvvf /usr/local/bin nerdctl-${NERDCTL_VERSION}-linux-${ARCH}.tar.gz
rm nerdctl-${NERDCTL_VERSION}-linux-${ARCH}.tar.gz
# Install useful kubectl aliases
curl -sSLO https://raw.githubusercontent.com/ahmetb/kubectl-aliases/master/.kubectl_aliases
echo '[ -f ~/.kubectl_aliases ] && source ~/.kubectl_aliases' >> .bashrc
Commenter la ligne dans /etc/fstab comme sur l’exemple pour définitivement désactiver le swap.
Setup proprement votre hostname :
hostnamectl set-hostname master
Puis ajouter votre IP et nom d’hôte dans le /etc/hosts
Assurez-vous que containerd.io ne fasse pas conflit :
sudo rm /etc/containerd/config.toml
sudo systemctl restart containerd
Ajouter au fichier /etc/docker/daemon.json
{ "exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts":
{ "max-size": "100m" },
"storage-driver": "overlay2"
}
Puis activer au démarrage :
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker
Redémarrer les machines.
Dans chacune des machines, chercher la ligne suivant au fichier /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
Environment="KUBELET_EXTRA_ARGS=--node-ip=192.168.45.170"
Vous devez changer l’ip pour mettre l’ip de la machine, ici c’est le master, et pour nos worker ce sera 192.168.45.171
et 192.168.45.172
par exemple.
Redémarrer kubelet pour valider.
sudo systemctl daemon-reload
sudo systemctl restart kubelet
Modifier /etc/containerd/config.toml pour y avoir le contenu suivant :
# Copyright 2018-2022 Docker Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
disabled_plugins = []
[plugins."io.containerd.grpc.v1.cri"]
systemd_cgroup = true
#root = "/var/lib/containerd"
#state = "/run/containerd"
#subreaper = true
#oom_score = 0
#[grpc]
# address = "/run/containerd/containerd.sock"
# uid = 0
# gid = 0
#[debug]
# address = "/run/containerd/debug.sock"
# uid = 0
# gid = 0
# level = "info"
Puis redémarrer : sudo systemctl restart containerd
Puis reboot
Prérequis pour le master
1) Editer le fichier /etc/docker/daemon.json et y ajouter :
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker
Master
1) Initialisez le contrôleur de cluster sur le master en utilisant la commande
sudo kubeadm init --apiserver-advertise-address=192.168.45.170 --apiserver-cert-extra-sans=192.168.45.170 --node-name=master --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=NumCPU,Mem
le flag --ignore-preflight-errors permet de forcer l'installation même si les requirements en terme de CPU et Mémoire ne sont pas respectés (cette option ne sera évidemment pas utilisée pour la mise en place d'un cluster de production)
2) Configurez kubectl pour utiliser le nouveau cluster en utilisant les commandes générées par la commande kubeadm init
rm -rf /home/$USER/.kube
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=$HOME/.kube/config
3) Mettez en place le réseau, ici avec flannel :
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
mkdir -p /run/flannel/
touch /run/flannel/subnet.env
Ajouter dans le fichier /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
Vous récupérerez une commande kubeadm join – Gardez la de côté ou vous pouvez la retrouver avec
sudo kubeadm token create --print-join-command
Exemple :
sudo kubeadm join 192.168.45.163:6443 --token tv6ynl.getnsnh1sa4u8j87 --discovery-token-ca-cert-hash sha256:9c6531aaa77ca6b3f145dc0b6ee7421ac1fefcb3421b22b5fd5474341451ba08
-----> [preflight] Running pre-flight checks
[...]
Worker
Ajoutez les 2 nœuds au cluster en utilisant la commande kubeadm join sur chacune des machines en utilisant les informations générées par la commande kubeadm init sur le master.
Créez un fichier de configuration pour chaque nœud avec la commande :
sudo kubeadm alpha node config --node-name=NODE_NAME > NODE_NAME-config.yaml
Appliquez la configuration pour chaque nœud en utilisant la commande :
sudo kubeadm join --config NODE_NAME-config.yaml
Ou copier simplement la commande précédemment générée de type :
kubeadm join 192.168.45.163:6443 --token tv6ynl.getnsnh1sa4u8j87 --discovery-token-ca-cert-hash sha256:9c6531aaa77ca6b3f145dc0b6ee7421ac1fefcb3421b22b5fd5474341451ba08
Configurez kubectl pour utiliser le nouveau cluster en utilisant les commandes générées par la commande kubeadm init
Exemple :
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Vérifiez que le cluster est opérationnel en exécutant la commande :
kubectl get nodes
Vérifiez que tous les nœuds sont en état "Ready
"
Utilisez les commandes de base de kubectl
pour gérer le cluster.
Troubleshooting
Reset le cluster en cas de problème pour refaire un kubeadm
init ou kubeadm join
ensuite.
sudo kubeadm reset -f
rm -rf $HOME/.kube/config
Puis refaire à partir l’étape 1 du master.
Redémarrer proprement
sudo systemctl daemon-reload
sudo systemctl stop kubelet
sudo systemctl start kubelet
sudo systemctl stop docker
sudo systemctl start docker
kubectl get pods -A -o wide
kubectl get pods -n kube-system
Supprimer flannel pour qu’il se reconstruise :
kubectl delete pods kube-flannel-ds-mjzjn -n kube-flannel
kubectl delete pods kube-flannel-ds-2ksgt -n kube-flannel
Liens utiles
- *https://github.com/kubernetes/kubeadm/issues/1026
- https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#check-certificate-expiration
- https://github.com/kubernetes/kubeadm/issues/1026#issuecomment-408457991
- https://serverfault.com/questions/1088776/kubernetes-api-server-not-able-to-register-master-node
- https://github.com/Hawaiideveloper/Infastructure-as-Code-Sample_Env/issues/15
- https://discuss.kubernetes.io/t/the-connection-to-the-server-localhost-8080-was-refused-did-you-specify-the-right-host-or-port/1464
- https://discuss.kubernetes.io/t/the-connection-to-the-server-192-168-1-2-6443-was-refused-did-you-specify-the-right-host-or-port/22260
- https://www.linuxtechi.com/install-kubernetes-cluster-on-debian/